home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*----------------------------------------------------------------------
- * Demonstration program for using the routines in PlayEngine.c.
- *----------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------
- * III N N CCC L U U DDDD EEEEE SSS
- * I NN N C C L U U D D E S S
- * I NN N C L U U D D E S
- * I N N N C L U U D D EEE SSS
- * I N NN C L U U D D E S
- * I N NN C C L U U D D E S S
- * III N N CCC LLLL UUU DDDD EEEEE SSS
- *----------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/prctl.h>
- #include <sys/time.h>
- #include <sys/schedctl.h>
- #include <sys/resource.h>
- #include <malloc.h>
-
- #include <fcntl.h>
-
- #include <audio.h>
- #include <audiofile.h>
-
- /*------------------------------------------------------------------------
- * DDDD EEEEE FFFFF III N N EEEEE SSS
- * D D E F I NN N E S S
- * D D E F I NN N E S
- * D D EEE FFF I N N N EEE SSS
- * D D E F I N NN E S
- * D D E F I N NN E S S
- * DDDD EEEEE F III N N EEEEE SSS
- *------------------------------------------------------------------------*/
-
- static char *ProgName;
- static int samps_per_frame; /* frame size */
- static int bytes_per_samp; /* sample width */
- static int bytes_per_buf; /* bytes / sample buffer */
- static int frames_per_buf; /* frames / sample buffer */
- static double secs_per_buf; /* time to play one sample buffer */
- static char *sampbuf; /* sample buffer */
- static double secs_per_frame; /* time to play one audio frame */
- static double file_rate; /* audio file sample rate */
- static long compression; /* audio data compression type */
- static long filefmt; /* input file format */
- static int samps_per_buf; /* samples / sample buffer */
- static long bits_per_samp; /* sample resolution */
- static int frames_per_sec; /* sample rate */
-
- AFfilehandle afHandle;
- ALport audio_port;
-
- int ndPriority = NDPHIMAX;
- int ProcessPriority = PRIO_MIN;
- int PGPriority = PRIO_MIN;
- int UserPriority = PRIO_MIN;
-
- /*------------------------------------------------------------------------
- * afError
- * Routine to handle audio file errors.
- *------------------------------------------------------------------------*/
-
- static void afError (long code, const char *desc)
- {
- fprintf(stderr, "%s: (Audio File Library error %d): %s\n", ProgName,
- code, desc);
- }
-
- /*------------------------------------------------------------------------
- * play_engine_thread
- * The routine that will be called to play audio data.
- *------------------------------------------------------------------------*/
-
- void play_engine_thread (void)
- {
- int num_bufs;
- int leftover_bytes;
- int leftover_samps;
- int leftover_frames;
- int samp_count;
- int frame_count;
- double sec_count;
- int i;
- int bytes_read;
- int samples_read;
- int frames_read;
- int done;
- int total_frames;
- int total_samps;
- int total_samp_bytes;
- float file_playingtime;
- char compressionname[10];
- float fileplayingtime;
-
- sec_count = 0.0;
-
- /*
- * figure out how many reads we have to do
- */
- total_frames = AFgetframecnt(afHandle, AF_DEFAULT_TRACK);
- if (total_frames > 0) {
- total_samps = total_frames * samps_per_frame;
- total_samp_bytes = total_samps * bytes_per_samp;
- num_bufs = total_samp_bytes / bytes_per_buf;
- leftover_bytes = total_samp_bytes % bytes_per_buf;
- leftover_samps = leftover_bytes / bytes_per_samp;
- leftover_frames = leftover_samps / samps_per_frame;
- } else {
- /* this could be an undertermined length raw file, or mpeg file */
- num_bufs = -1;
- }
-
- /*
- * move the fileptr to the beginning of the sample data
- */
- AFseekframe(afHandle, AF_DEFAULT_TRACK, 0);
-
- /*
- * note that there may be some pad bytes following the valid samples -
- * for example, the sample data area may be padded so that the valid
- * samples begin on a block boundary and the sample area ends on a block
- * boundary (where blocksize is specified by the user)
- */
- done = 0;
- samp_count = 0;
- frame_count = 0;
- sec_count = 0.0;
-
- for (i=0; num_bufs<0 || i<num_bufs; i++)
- {
- samp_count += samps_per_buf;
- frame_count += frames_per_buf;
- sec_count += secs_per_buf;
-
- if ((frames_read
- = AFreadframes(afHandle, AF_DEFAULT_TRACK,
- sampbuf, frames_per_buf)) < frames_per_buf)
- {
- done++;
- }
- samples_read = frames_read * samps_per_frame;
- ALwritesamps(audio_port, sampbuf, samples_read);
- if (done)
- {
- /*
- * allow the audio buffer to drain
- */
- while(ALgetfilled(audio_port) > 0) {
- sginap(1);
- }
- sginap(10);
- return;
- }
- }
- /*
- * play the leftovers
- */
- samp_count += leftover_samps;
- frame_count += leftover_frames;
- sec_count += ((double)leftover_frames) * secs_per_frame;
- frames_read = AFreadframes(afHandle, AF_DEFAULT_TRACK, sampbuf,
- leftover_frames);
- samples_read = frames_read * samps_per_frame;
- ALwritesamps(audio_port, sampbuf, samples_read);
-
- /*
- * allow the audio buffer to drain
- */
- while(ALgetfilled(audio_port) > 0) {
- sginap(1);
- }
- sginap(10);
- return;
- }
-
- /* ******************************************************************
- * GetInputRate: return Audio Hardware input sampling rate
- * ****************************************************************** */
- int
- GetInputRate()
- {
- long buf[6];
-
- buf[0] = AL_INPUT_RATE;
- buf[2] = AL_INPUT_SOURCE;
- buf[4] = AL_DIGITAL_INPUT_RATE;
- ALgetparams(AL_DEFAULT_DEVICE, buf, 6);
-
- /* we are clocked off digital input. find real input rate, if possible. */
- if ((buf[1] == AL_RATE_AES_1)||(buf[3] == AL_INPUT_DIGITAL))
- {
- if (ALgetdefault(AL_DEFAULT_DEVICE, AL_DIGITAL_INPUT_RATE) >= 0)
- return (buf[5]);
- }
- /* input rate is Hz and we're using an analog input */
- else if (buf[1] > 0)
- return (buf[1]);
-
- return (AL_RATE_UNDEFINED);
- } /* --------------------- end GetInputRate() --------------- */
-
- /* ******************************************************************
- * GetOutputRate: return Audio Hardware output sampling rate
- * ****************************************************************** */
- int
- GetOutputRate()
- {
- long buf[4];
-
- buf[0] = AL_OUTPUT_RATE;
- buf[2] = AL_DIGITAL_INPUT_RATE;
- ALgetparams(AL_DEFAULT_DEVICE, buf, 4);
-
- /* output rate is in Hz -- return it */
- if (buf[1] > 0)
- return (buf[1]);
-
- /* output rate is logical -- track down what it means */
- else
- {
- if (buf[1] == AL_RATE_AES_1)
- {
- /* we are clocked off of digital input. find
- * real input rate, if system supports this ability.
- * Otherwise, return AL_RATE_UNDEFINED */
- if (ALgetdefault(AL_DEFAULT_DEVICE,AL_DIGITAL_INPUT_RATE) >= 0)
- return (buf[3]);
- }
- else if (buf[1] == AL_RATE_INPUTRATE)
- return (GetInputRate());
- return (AL_RATE_UNDEFINED);
- }
- } /* --------------------- end GetOutputRate() --------------- */
-
- /* ******************************************************************
- * InitAudio(): initialize audio port and global state of IRIS Audio
- * Hardware
- * ****************************************************************** */
- static int
- InitAudio(AFfilehandle audio_file, ALport *audio_port)
- {
- ALconfig audio_port_config;
- long pvbuf[4];
- long audio_rate, output_rate;
- long samp_type;
- long samp_wordsize;
- long vers;
- int err;
-
- samps_per_frame = AFgetchannels(audio_file, AF_DEFAULT_TRACK);
- file_rate = AFgetrate(audio_file, AF_DEFAULT_TRACK);
- compression = AFgetcompression(audio_file, AF_DEFAULT_TRACK);
- filefmt = AFgetfilefmt(audio_file, &vers);
-
- AFgetsampfmt(audio_file, AF_DEFAULT_TRACK, &samp_type, &bits_per_samp);
-
- /*
- * need to determine whether audio is in use. if not, then we
- * can just go ahead and be "rude."
- */
- pvbuf[0] = AL_OUTPUT_COUNT;
- pvbuf[2] = AL_MONITOR_CTL;
- if (ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 4) < 0) {
- if (oserror() == AL_BAD_DEVICE_ACCESS) {
- fprintf(stderr,"%s: Can't play -- could not access audio "
- "hardware.\n",ProgName);
- return -1;
- }
- }
-
-
- /*
- * decide on output rate for the audio hardware
- */
- audio_rate = frames_per_sec = (long) file_rate;
-
-
- /*
- * determine current output rate
- */
- output_rate = GetOutputRate();
-
- /*
- * if the rates are the same, all is well. if not, then we need to proceed
- * in a either a "rude" or "polite" manner.
- */
-
- if (output_rate != audio_rate)
- {
- /*
- * we set the rate to our value in Hz. ALsetparams will set
- * the hardware to the closest rate to audio_rate which the
- * hardware supports.
- */
-
- output_rate = audio_rate;
- pvbuf[0] = AL_OUTPUT_RATE;
- pvbuf[1] = output_rate;
- ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
- }
-
-
- /*
- * decide what size blocks of samples we should read from the
- * input file and pass to ALwritesamps
- */
- if (bits_per_samp <= 8)
- {
- bytes_per_samp = 1;
- samp_wordsize = AL_SAMPLE_8;
- }
- else if (bits_per_samp <= 16)
- {
- bytes_per_samp = 2;
- samp_wordsize = AL_SAMPLE_16;
- }
- else if (bits_per_samp <= 24)
- {
- bytes_per_samp = 4;
- samp_wordsize = AL_SAMPLE_24;
- }
- else
- {
- return(-1);
- }
-
- if ((samps_per_frame != 1)&&(samps_per_frame!= 2)&&(samps_per_frame!=4))
- {
- return(-1);
- }
-
- /*
- * make the buffer large enough to hold 1/2 sec of audio frames
- * we add one to frames_per_sec before we divide in order to
- * correctly handle the 11025 case
- */
- secs_per_frame = 1.0 / ((double)frames_per_sec);
- frames_per_buf = (frames_per_sec+1)/2;
-
- samps_per_buf = frames_per_buf * samps_per_frame;
- bytes_per_buf = samps_per_buf * bytes_per_samp;
- secs_per_buf = secs_per_frame * frames_per_buf;
-
- sampbuf = malloc(bytes_per_buf);
-
- /*
- * configure and open audio port
- */
- audio_port_config = ALnewconfig();
- ALsetwidth(audio_port_config, samp_wordsize);
- ALsetchannels(audio_port_config, samps_per_frame);
-
- /*
- * make the ring buffer large enough to hold 1 sec of audio samples
- */
- ALsetqueuesize(audio_port_config, samps_per_buf*2);
- *audio_port = ALopenport(ProgName, "w", audio_port_config);
- if (*audio_port == 0) {
- err = oserror();
- if (err == AL_BAD_NO_PORTS) {
- fprintf(stderr,"%s: Can't play -- no audio ports available at the moment\n",ProgName);
- }
- else if (err == AL_BAD_OUT_OF_MEM) {
- fprintf(stderr,"%s: Can't play -- not enough memory to open audio port\n",ProgName);
- }
- return -1;
- }
- } /* --------------------- end InitAudio() --------------- */
-
- /*========================================================================
- * MAIN
- *========================================================================*/
-
- main (int argc, char *argv[])
- {
- int fd;
-
- ProgName = strrchr (argv[0], '/');
- if (ProgName)
- ProgName++;
- else
- ProgName = argv[0];
-
- if (argc < 2)
- {
- fprintf (stderr, "Usage: %s <audio-file>\n", ProgName);
- exit (0);
- }
-
- AFseterrorhandler (afError);
-
- #if 1
- if ((fd = open (argv[1], O_RDONLY)) < 0)
- {
- fprintf (stderr, "%s: Error opening file %s\n", ProgName, argv[1]);
- exit (1);
- }
- else if (AFidentifyfd (fd) < 0)
- {
- fprintf (stderr, "%s: %s is not an AIFF-C or AIFF file.\n", ProgName,
- argv[1]);
- exit (1);
- }
-
- afHandle = AFopenfd (fd, "r", AF_NULL_FILESETUP);
- #else
- afHandle = AFopenfile (argv[1], "r", AF_NULL_FILESETUP);
- #endif
- if (afHandle == AF_NULL_FILEHANDLE)
- {
- fprintf (stderr, "%s: Unable to open file %s for reading.\n",
- ProgName, argv[1]);
- exit (1);
- }
-
- if (InitAudio (afHandle, &audio_port) < 0)
- {
- fprintf (stderr, "%s: Problem initializing audio.\n", ProgName);
- exit (2);
- }
-
- CreateSubProcess ();
-
- StartSubProcess ();
-
- WaitForSubProcess ();
-
- DestroySubProcess ();
-
- AFclosefile (afHandle);
- }
-